import 'package:demo_day_1/constants/api_constants.dart';
import 'package:dio/dio.dart';

class ApiClient {
  static final ApiClient _instance = ApiClient._internal(); // 单例模式

  factory ApiClient() {
    return _instance;
  }

  ApiClient._internal() {
    _dio = Dio(BaseOptions(
      baseUrl: ApiConstants.gitcodeApiBaseUrl, // 从常量中获取基地址
      connectTimeout: const Duration(seconds: 10), // 连接超时时间
      receiveTimeout: const Duration(seconds: 10), // 接收超时时间
      headers: {
        'Accept': 'application/json', // 默认接受 JSON 响应
      },
    ));

    // 添加日志拦截器，方便开发时调试
    _dio.interceptors.add(LogInterceptor(
      requestBody: true,
      responseBody: true,
      error: true,
    ));
  }

  late Dio _dio;
  String? _accessToken; // 用于存储 Access Token

  // 获取 Dio 实例
  Dio get dio => _dio;

  // 设置 Access Token，并重新配置认证拦截器
  void setAccessToken(String? token) {
    _accessToken = token;
    _configureAuthInterceptor();
  }

  // 配置认证拦截器
  void _configureAuthInterceptor() {
    // 移除旧的认证拦截器，避免重复
    _dio.interceptors.removeWhere((interceptor) => interceptor is InterceptorsWrapper && interceptor.runtimeType.toString() == '_AuthInterceptorWrapper');

    if (_accessToken != null && _accessToken!.isNotEmpty) {
      _dio.interceptors.add(
        InterceptorsWrapper(
          // 添加一个标识，方便后续移除
          // ignore: non_constant_identifier_names
          onRequest: (options, handler) {
            options.headers['Authorization'] = 'Bearer $_accessToken';
            return handler.next(options);
          },
          // 可以添加 onError 处理，例如 Token 过期自动刷新
          onError: (DioException error, handler) async {
            if (error.response?.statusCode == 401) {
              // 401 Unauthorized，可能是 Token 过期
              // TODO: 在这里实现 Token 刷新逻辑，如果需要的话
              print('Authentication error: Token expired or invalid.');
              // 例如：Navigator.of(error.requestOptions.context!).pushReplacement(MaterialPageRoute(builder: (context) => LoginScreen()));
            }
            return handler.next(error); // 继续传递错误
          },
        ),
      );
    }
  }

  // 封装常用的 HTTP 方法
  Future<Response<T>> get<T>(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onReceiveProgress,
  }) async {
    try {
      return await _dio.get(
        path,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
        onReceiveProgress: onReceiveProgress,
      );
    } on DioException catch (e) {
      // 统一的错误处理
      _handleDioError(e);
      rethrow; // 重新抛出，让调用者也能捕获
    }
  }

  Future<Response<T>> post<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) async {
    try {
      return await _dio.post(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
        onSendProgress: onSendProgress,
        onReceiveProgress: onReceiveProgress,
      );
    } on DioException catch (e) {
      _handleDioError(e);
      rethrow;
    }
  }

  Future<Response<T>> put<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) async {
    try {
      return await _dio.put(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
        onSendProgress: onSendProgress,
        onReceiveProgress: onReceiveProgress,
      );
    } on DioException catch (e) {
      _handleDioError(e);
      rethrow;
    }
  }

  Future<Response<T>> delete<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    try {
      return await _dio.delete(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      );
    } on DioException catch (e) {
      _handleDioError(e);
      rethrow;
    }
  }

  // 统一的 Dio 错误处理
  void _handleDioError(DioException error) {
    String errorMessage = '未知网络错误';
    switch (error.type) {
      case DioExceptionType.connectionTimeout:
        errorMessage = '连接超时，请检查网络设置。';
        break;
      case DioExceptionType.sendTimeout:
        errorMessage = '请求发送超时。';
        break;
      case DioExceptionType.receiveTimeout:
        errorMessage = '服务器响应超时。';
        break;
      case DioExceptionType.badResponse:
        // 根据状态码处理具体的业务错误
        errorMessage = '服务器错误：${error.response?.statusCode ?? ''} - ${error.response?.statusMessage ?? '未知错误'}';
        // 可以在这里解析 error.response.data 来获取后端返回的错误信息
        break;
      case DioExceptionType.cancel:
        errorMessage = '请求已取消。';
        break;
      case DioExceptionType.badCertificate:
        errorMessage = 'SSL 证书验证失败。';
        break;
      case DioExceptionType.connectionError:
        errorMessage = '连接错误，请检查您的网络连接。';
        break;
      case DioExceptionType.unknown:
        errorMessage = '发生未知网络错误: ${error.message}';
        break;
    }
    print('Dio Error: $errorMessage');
    // 可以在这里抛出自定义的异常，或者通知 UI
    // throw CustomApiException(errorMessage);
  }
}